#include "Scene.h"
#include "GullEngine.h"

using namespace std;
using namespace gull::core;

Scene::Scene():
m_camera(NULL)
{
    m_sceneGraph = new SceneGraph;
	m_base = new Matrix4x3();
	m_sceneMatrixStack.push(m_base);
	theGullSceneManager->setActiveScene(this);
}


Scene::~Scene()
{
	delete m_sceneGraph;
}


void 
Scene::pushAndSetMatrix(const Matrix4x3& m)
{
    Matrix4x3* matrixStack = m_sceneMatrixStack.top();
    Matrix4x3* newMatrixStack = new Matrix4x3(m*(*matrixStack));
    m_sceneMatrixStack.push(newMatrixStack);
	theGullGraphicsManager->get3DAPI()->setMatrixWorld(*newMatrixStack);
}



void 
Scene::popAndSetMatrix()
{
	Matrix4x3* m = m_sceneMatrixStack.top();
	m_sceneMatrixStack.pop();
	delete m;
	Matrix4x3* matrixStack = m_sceneMatrixStack.top();
	theGullGraphicsManager->get3DAPI()->setMatrixWorld(*matrixStack);
}

void
Scene::renderScene()
{
	initStackMatrix();
	
	setCamera();
	SceneNode* root = getRoot();
	if(root)
	{
		root->preRender(this);
		root->render(this);
		root->postRender(this);
	}
}

void
Scene::initStackMatrix()
{
	while(!m_sceneMatrixStack.empty())
		m_sceneMatrixStack.pop();
	
	m_sceneMatrixStack.push(m_base);
}

void
Scene::setCamera()
{
	TransformController* tr = static_cast<TransformController*>(m_camera->getController(TRANSFORM));
	Matrix4x3* m = (tr->getMatrix());
	pushAndSetMatrix(m->inverse());
}


void
Scene::attachCamera(CameraNode& cam)
{
	if(m_camera)
		delete m_camera;
	m_camera = &cam;
}

